package com.huhao.wshare.controller;

import com.huhao.wshare.dto.AjaxResult;
import com.huhao.wshare.dto.User.Request.UserLoginRequest;
import com.huhao.wshare.dto.User.Response.*;
import com.huhao.wshare.dto.User.Request.UserPasswordUpdateRequest;
import com.huhao.wshare.dto.User.Request.UserRegisterRequest;
import com.huhao.wshare.dto.User.Request.UserUpdateRequest;
import com.huhao.wshare.entity.User;
import com.huhao.wshare.service.UserService;
import com.huhao.wshare.service.VerifyCodeService;
import com.huhao.wshare.service.constant.VerificationCodeType;
import com.huhao.wshare.service.security.CustomUserDetails;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * 用户控制器
 * 负责处理与用户账户相关的HTTP请求，包括注册、登录、登出、个人资料和密码的管理。
 */
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;
    private final VerifyCodeService verifyCodeService;

    // --- 公开端点 (无需认证) ---

    /**
     * 功能: 用户注册。
     * 路径: POST /api/auth/register
     * 认证: 无需认证。
     * @param registerRequest 包含用户注册信息的请求体 (account, password, email, phone, verificationCode等)。
     * @return 注册成功后，返回包含新用户信息和 200 OK 状态的响应。
     */
    @PostMapping("/auth/register")
    public ResponseEntity<UserRegisterSuccessResponse> registerUser(@Valid @RequestBody UserRegisterRequest registerRequest) {
        User registeredUser = userService.register(registerRequest, registerRequest.getVerificationCode());
        UserRegisterSuccessResponse response = UserRegisterSuccessResponse.fromUser(registeredUser);
        // --- 修改点：将 HTTP 状态从 201 Created 改为 200 OK ---
        return ResponseEntity.ok(response);
    }


    /**
     * 功能: 用户登录。
     * 路径: POST /api/auth/login
     * 认证: 无需认证。
     * @param loginRequest 包含用户登录凭证的请求体 (identifier, password)。identifier可以是账号、邮箱或手机号。
     * @return 登录成功后，返回包含JWT令牌、用户ID、用户名的响应和 200 OK 状态。
     */
    @PostMapping("/auth/login")
    public ResponseEntity<LoginResponse> loginUser(@Valid @RequestBody UserLoginRequest loginRequest) {
        LoginResponse loginResponse = userService.login(loginRequest);
        return ResponseEntity.ok(loginResponse);
    }

    /**
     * 功能: 根据用户 ID 获取指定用户的详细个人信息。
     * 路径: GET /api/auth/profile/{userId}
     * 认证: 需要认证 (有效的 Bearer Token)。
     * @param userId 要查询的用户的ID (从URL路径中获取)。
     * @return 包含用户详细信息的标准响应体，或在用户不存在时返回 401 错误。
     */
    @GetMapping("/auth/profile/{userId}")
    public ResponseEntity<?> getUserProfile(@PathVariable Long userId) {
        try {
            // 1. 调用服务层获取原始的 profile 数据 DTO
            UserProfileResponse userProfileData = userService.getUserProfile(userId);

            // 2. 构建成功的标准响应体
            UserProfileSuccessResponse response = UserProfileSuccessResponse.builder()
                    .code(HttpStatus.OK.value()) // 200
                    .data(userProfileData)
                    .message("用户信息获取成功！")
                    .build();

            // 3. 返回成功的响应
            return ResponseEntity.ok(response);

        } catch (IllegalArgumentException ex) {
            // 4. 捕获用户不存在的异常，并按要求返回 401 错误
            // 通常，"资源不存在" 返回 404 Not Found 更为标准，但这里遵从您的设计要求返回 401。
            Map<String, Object> errorBody = new HashMap<>();
            errorBody.put("code", HttpStatus.UNAUTHORIZED.value()); // 401
            errorBody.put("errorType", "业务逻辑错误");
            // 使用从 Service 层抛出的异常信息，例如 "错误：用户不存在！"
            errorBody.put("message", ex.getMessage());

            return new ResponseEntity<>(errorBody, HttpStatus.UNAUTHORIZED);
        }
    }

    // --- 需要认证的端点 (需要有效的JWT令牌) ---

    /**
     * 功能: 用户登出。
     * 路径: POST /api/user/logout
     * 认证: 需要认证。
     * @param currentUser Spring Security通过 @AuthenticationPrincipal 注解自动注入的当前用户信息。
     * @return 返回包含成功代码和消息的响应体及 200 OK 状态。
     */
    @PostMapping("/auth/logout")
    public ResponseEntity<Map<String, Object>> logoutUser(@AuthenticationPrincipal CustomUserDetails currentUser) {
        userService.logout(currentUser.getUsername());

        // 构建包含 code 和 message 的标准响应体
        Map<String, Object> responseBody = new HashMap<>();
        responseBody.put("code", HttpStatus.OK.value()); // 200
        responseBody.put("message", "用户已成功登出。");

        return ResponseEntity.ok(responseBody);
    }


    /**
     * 功能: 更新当前登录用户的个人资料。
     * 路径: PUT /api/user/profile
     * 认证: 需要认证。
     * @param request 包含要更新字段的请求体 (如 username, signs, avatar等)。
     * @param currentUser Spring Security自动注入的当前用户信息。
     * @return 包含更新后用户信息的标准响应体和 200 OK 状态。
     */
    @PutMapping("/user/profile")
    public ResponseEntity<UserUpdateSuccessResponse> updateUserProfile(
            @Valid @RequestBody UserUpdateRequest request,
            @AuthenticationPrincipal CustomUserDetails currentUser) {
        User updatedUser = userService.updateUserProfile(currentUser.getUser().getId(), request);
        UserProfileResponse userProfileData = UserProfileResponse.fromUser(updatedUser);
        UserUpdateSuccessResponse response = UserUpdateSuccessResponse.builder()
                .code(HttpStatus.OK.value())
                .data(userProfileData)
                .message("用户信息更新成功！")
                .build();
        return ResponseEntity.ok(response);
    }

    // --- 密码修改相关端点 ---

    /**
     * 功能: 请求发送用于更新密码的邮箱验证码。
     * 路径: POST /api/user/password/send-code
     * 认证: 需要认证。
     * @param currentUser Spring Security自动注入的当前用户信息，用于获取其注册邮箱。
     * @return 包含成功或失败信息的标准响应体 (AjaxResult)。
     */
    @PostMapping("/user/password/send-code")
    public AjaxResult<String> sendPasswordUpdateCode(@AuthenticationPrincipal CustomUserDetails currentUser) {
        String email = currentUser.getUser().getEmail();
        return verifyCodeService.sendVerificationCode(email, VerificationCodeType.PASSWORD_RESET);
    }

    /**
     * 功能: 更新当前用户的密码。
     * 路径: PUT /api/user/password
     * 认证: 需要认证。
     * @param currentUser Spring Security自动注入的当前用户信息。
     * @param request 包含新密码和从邮箱收到的验证码的请求体。
     * @return 包含成功代码和消息的响应体及 200 OK 状态。
     */
    @PutMapping("/user/password")
    public ResponseEntity<Map<String, Object>> updatePassword( // 返回类型修改为 Map<String, Object>
                                                               @AuthenticationPrincipal CustomUserDetails currentUser,
                                                               @Valid @RequestBody UserPasswordUpdateRequest request) {
        userService.updatePassword(currentUser.getUser().getId(), request);

        // 构建包含 code 和 message 的标准响应体
        Map<String, Object> responseBody = new HashMap<>();
        responseBody.put("code", HttpStatus.OK.value()); // 200
        responseBody.put("message", "密码更新成功。");

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 【修改】
     * 功能: 根据用户的唯一标识(邮箱、手机号或账号)查询用户，并判断与当前用户的关系。
     * 路径: GET /api/user/find
     * 认证: 需要认证。
     * @param identifier  用户的邮箱、手机号或账号 (作为请求参数)。
     * @param currentUser Spring Security 自动注入的当前登录用户信息。
     * @return 包含用户ID和是否为好友状态的响应体。
     */
    @GetMapping("/user/find-id") // 路径从 /find-id 修改为 /find
    public ResponseEntity<Map<String, Object>> findUserByIdentifier(
            @RequestParam String identifier,
            @AuthenticationPrincipal CustomUserDetails currentUser) {

        // 1. 调用更新后的服务方法
        UserSearchResponse searchResult = userService.findUserByIdentifier(currentUser.getUser().getId(), identifier);

        // 2. 构建 data 部分
        Map<String, Object> data = new HashMap<>();
        data.put("userId", searchResult.getUserId());
        data.put("isFriend", searchResult.isFriend());

        // 3. 构建完整的标准响应体
        Map<String, Object> responseBody = new HashMap<>();
        responseBody.put("code", HttpStatus.OK.value());
        responseBody.put("message", "用户查询成功");
        responseBody.put("data", data); // 将 userId 和 isFriend 嵌套在 data 对象中

        return ResponseEntity.ok(responseBody);
    }


    // --- 统一异常处理器 ---

    /**
     * 功能: 处理 @Valid 注解触发的参数校验异常。
     * @param ex MethodArgumentNotValidException 异常实例。
     * @return 包含所有字段错误信息的响应体和 400 Bad Request 状态。
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Map<String, Object> handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getAllErrors().forEach((error) -> {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            errors.put(fieldName, errorMessage);
        });
        Map<String, Object> response = new HashMap<>();
        response.put("code", HttpStatus.BAD_REQUEST.value());
        response.put("message", "参数校验失败");
        response.put("errors", errors);
        response.put("errorType", "参数校验失败");
        return response;
    }

    /**
     * 功能: 处理业务逻辑中抛出的常见异常 (如用户不存在、密码错误、权限不足等)。
     * @param ex 捕获到的异常实例。
     * @return 包含错误信息的响应体和适当的HTTP状态码 (400或403)。
     */
    @ExceptionHandler({IllegalArgumentException.class, SecurityException.class, IllegalStateException.class})
    public ResponseEntity<Map<String, Object>> handleBusinessExceptions(Exception ex) {
        Map<String, Object> errorDetails = new HashMap<>();
        HttpStatus status;
        String errorType;

        if (ex instanceof SecurityException) {
            status = HttpStatus.FORBIDDEN;
            errorType = "权限不足";
        } else {
            status = HttpStatus.BAD_REQUEST;
            errorType = "业务逻辑错误";
        }

        errorDetails.put("code", status.value());
        errorDetails.put("message", ex.getMessage());
        errorDetails.put("errorType", errorType);

        return new ResponseEntity<>(errorDetails, status);
    }
}
